package top.yj95.codegenerator.util;

import com.baomidou.mybatisplus.annotation.IdType;

import cn.hutool.core.lang.Console;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;

/**
 * 代码生成器助手
 * @author 杨军
 * @date 2022-04-10
 */
public class CGHelper {
	
	/**
	 * 从Oracle数据库中读取指定表的信息，并生成相关的代码。启用 swagger2 模式，Mapper XML不写入到<code>src/main/resources</code>目录下。
	 * @param outputDir 输出目录（输出目录为空白时，将输出到当前用户主目录下的<code>CodeGenerator</code>目录）
	 * @param host 数据库主机地址
	 * @param userName 用户名
	 * @param password 密码
	 * @param parent 父包名
	 * @param moduleName 父模块名
	 * @param author 作者
	 * @param include 要生成代码的表
	 * @param tablePrefix 表名前缀
	 * @author 杨军
	 * @date 2022-04-10
	 */
	public static void generateFromOracle(String outputDir, String host, String userName, String password, String parent,
		String moduleName, String author, String[] include, String[] tablePrefix) {
		generateFromOracle(true, false, outputDir, host, userName, password, parent, moduleName, author, include, tablePrefix);
	}
	
	/**
	 * 从Oracle数据库中读取指定表的信息，并生成相关的代码。
	 * @param swagger2 是否开启 swagger2 模式
	 * @param writeXmlToResources 是否将 Mapper XML 写入到<code>src/main/resources</code>目录下
	 * @param outputDir 输出目录（输出目录为空白时，将输出到当前用户主目录下的<code>CodeGenerator</code>目录）
	 * @param host 数据库主机地址
	 * @param userName 用户名
	 * @param password 密码
	 * @param parent 父包名
	 * @param moduleName 父模块名
	 * @param author 作者
	 * @param include 要生成代码的表
	 * @param tablePrefix 表名前缀
	 * @author 杨军
	 * @date 2022-04-10
	 */
	public static void generateFromOracle(boolean swagger2, boolean writeXmlToResources, String outputDir, String host, String userName, String password, 
		String parent, String moduleName, String author, String[] include, String[] tablePrefix) {
		final String urlHead = "jdbc:oracle:thin:@";
		// Oracle没有自增长主键，因此主键策略只能固定为INPUT
		generateCode(swagger2, writeXmlToResources, outputDir, urlHead, host, userName, password, parent, moduleName, author, IdType.INPUT, include, 
			tablePrefix);
	}
	
	/**
	 * 从MySQL数据库中读取指定表的信息，并生成相关的代码。启用 swagger2 模式，Mapper XML不写入到<code>src/main/resources</code>目录下，
	 * 主键策略使用{@link IdType#AUTO}。
	 * @param outputDir 输出目录（输出目录为空白时，将输出到当前用户主目录下的<code>CodeGenerator</code>目录）
	 * @param host 数据库主机地址
	 * @param userName 用户名
	 * @param password 密码
	 * @param parent 父包名
	 * @param moduleName 父模块名
	 * @param author 作者
	 * @param include 要生成代码的表
	 * @param tablePrefix 表名前缀
	 * @author 杨军
	 * @date 2022-04-10
	 */
	public static void generateFromMySQL(String outputDir, String host, String userName, String password, String parent,
		String moduleName, String author, String[] include, String[] tablePrefix) {
		generateFromMySQL(true, false, outputDir, host, userName, password, parent, moduleName, author, IdType.AUTO, include, tablePrefix);
	}
	
	/**
	 * 从MySQL数据库中读取指定表的信息，并生成相关的代码。
	 * @param swagger2 是否开启 swagger2 模式
	 * @param writeXmlToResources 是否将 Mapper XML 写入到<code>src/main/resources</code>目录下
	 * @param outputDir 输出目录（输出目录为空白时，将输出到当前用户主目录下的<code>CodeGenerator</code>目录）
	 * @param host 数据库主机地址
	 * @param userName 用户名
	 * @param password 密码
	 * @param parent 父包名
	 * @param moduleName 父模块名
	 * @param author 作者
	 * @param idType 主键策略
	 * @param include 要生成代码的表
	 * @param tablePrefix 表名前缀
	 * @author 杨军
	 * @date 2022-04-10
	 */
	public static void generateFromMySQL(boolean swagger2, boolean writeXmlToResources, String outputDir, String host, String userName, String password, 
		String parent, String moduleName, String author, IdType idType, String[] include, String[] tablePrefix) {
		final String urlHead = "jdbc:mysql://";
		generateCode(swagger2, writeXmlToResources, outputDir, urlHead, host, userName, password, parent, moduleName, author, idType, include, tablePrefix);
	}
	
	/**
	 * 从SQLite数据库中读取指定表的信息，并生成相关的代码。启用 swagger2 模式，Mapper XML不写入到<code>src/main/resources</code>目录下，
	 * 主键策略使用{@link IdType#AUTO}。
	 * @param outputDir 输出目录（输出目录为空白时，将输出到当前用户主目录下的<code>CodeGenerator</code>目录）
	 * @param host 数据库主机地址
	 * @param parent 父包名
	 * @param moduleName 父模块名
	 * @param author 作者
	 * @param idType 主键策略
	 * @param include 要生成代码的表
	 * @param tablePrefix 表名前缀
	 * @author 杨军
	 * @date 2022-04-10
	 */
	public static void generateFromSqlite(String outputDir, String host, String parent, String moduleName, String author, String[] include, String[] tablePrefix) {
		final String urlHead = "jdbc:sqlite:";
		generateCode(true, false, outputDir, urlHead, host, null, null, parent, moduleName, author, IdType.AUTO, include, tablePrefix);
	}

	/**
	 * 从SQLite数据库中读取指定表的信息，并生成相关的代码。
	 * @param swagger2 是否开启 swagger2 模式
	 * @param writeXmlToResources 是否将 Mapper XML 写入到<code>src/main/resources</code>目录下
	 * @param outputDir 输出目录（输出目录为空白时，将输出到当前用户主目录下的<code>CodeGenerator</code>目录）
	 * @param host 数据库主机地址
	 * @param parent 父包名
	 * @param moduleName 父模块名
	 * @param author 作者
	 * @param idType 主键策略
	 * @param include 要生成代码的表
	 * @param tablePrefix 表名前缀
	 * @author 杨军
	 * @date 2022-04-10
	 */
	public static void generateFromSqlite(boolean swagger2, boolean writeXmlToResources, String outputDir, String host, String parent, String moduleName, 
		String author, IdType idType, String[] include, String[] tablePrefix) {
		final String urlHead = "jdbc:sqlite:";
		generateCode(swagger2, writeXmlToResources, outputDir, urlHead, host, null, null, parent, moduleName, author, idType, include, tablePrefix);
	}
	
	/**
	 * 从数据库中读取指定表的信息，并生成相关的代码。
	 * @param swagger2 是否开启 swagger2 模式
	 * @param writeXmlToResources 是否将 Mapper XML 写入到<code>src/main/resources</code>目录下
	 * @param outputDir 输出目录（输出目录为空白时，将输出到当前用户主目录下的<code>CodeGenerator</code>目录）
	 * @param urlHead 数据库地址描述头
	 * @param host 数据库主机地址
	 * @param userName 用户名
	 * @param password 密码
	 * @param parent 父包名
	 * @param moduleName 父模块名
	 * @param author 作者
	 * @param idType 主键策略
	 * @param include 要生成代码的表
	 * @param tablePrefix 表名前缀
	 * @author 杨军
	 * @date 2022-04-10
	 */
	private static void generateCode(boolean swagger2, boolean writeXmlToResources, String outputDir, String urlHead, String host, String userName, 
		String password, String parent, String moduleName, String author, IdType idType, String[] include, String[] tablePrefix) {
		host = StrUtil.trimToEmpty(host);
		userName = StrUtil.trimToEmpty(userName);
		password = StrUtil.trimToEmpty(password);
		parent = StrUtil.trimToEmpty(parent);
		moduleName = StrUtil.trimToEmpty(moduleName);
		author = StrUtil.trimToEmpty(author);
		include = ArrayUtil.removeBlank(include);
		tablePrefix = ArrayUtil.removeBlank(tablePrefix);
		if (StrUtil.isBlank(host)) {
			Console.error("数据库地址不能为空白");
			return;
		}
		if (ArrayUtil.isEmpty(include)) {
			Console.log("没有需要生成代码的表");
			return;
		}
		if (StrUtil.isBlank(outputDir)) {
			outputDir = null;
		}
		if (StrUtil.isBlank(userName)) {
			userName = null;
		}
		if (StrUtil.isBlank(password)) {
			password = null;
		}
		String url = host.startsWith(urlHead) ? host : StrUtil.format("{}{}", urlHead, host);
		// 构建生成器并生成代码
		CodeGenerator.custom(url, userName, password, parent, moduleName, include).outputDir(outputDir)
			.tablePrefix(tablePrefix).author(author).idType(idType).swagger2(swagger2)
			.writeXmlToResources(writeXmlToResources).build().execute();
	}
	
	private CGHelper() {}
	
}
